#ifndef __ATLGDIX_H__
#define __ATLGDIX_H__

/////////////////////////////////////////////////////////////////////////////
// Additional GDI/USER wrappers
//
// Written by Bjarke Viksoe (bjarke@viksoe.dk)
// Copyright (c) 2001-2002 Bjarke Viksoe.
// Thanks to Daniel Bowen for COffscreenDrawRect.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. 
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#pragma once

#ifndef __cplusplus
   #error ATL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLGDI_H__
   #error atlgdix.h requires atlgdi.h to be included first
#endif

//#include "f:\project\web\browser\src\SogouBrowser\MainUIFrame\UIControl\Utility.h"

namespace WTL
{

/////////////////////////////////////////////////////////////////////////////
// Macros

// The GetXValue macros below are badly designed and emit
// compiler warnings e.g. when using RGB(255,255,255)...
#pragma warning(disable : 4310)

#ifndef BlendRGB
   #define BlendRGB(c1, c2, factor) \
      RGB( GetRValue(c1) + ((GetRValue(c2) - GetRValue(c1)) * factor / 100L), \
           GetGValue(c1) + ((GetGValue(c2) - GetGValue(c1)) * factor / 100L), \
           GetBValue(c1) + ((GetBValue(c2) - GetBValue(c1)) * factor / 100L) );
#endif

#ifndef COLOR_INVALID
   #define COLOR_INVALID  (COLORREF) CLR_INVALID
#endif


/////////////////////////////////////////////////////////////////////////////
// CIcon

// template< bool t_bManaged >
// class CIconT
// {
// public:
//    HICON m_hIcon;
// 
//    // Constructor/destructor/operators
// 
//    CIconT(HICON hIcon = NULL) : m_hIcon(hIcon)
//    { }
// 
//    ~CIconT()
//    {
//       if( t_bManaged && m_hIcon != NULL ) ::DestroyIcon(m_hIcon);
//    }
// 
//    CIconT<t_bManaged>& operator=(HICON hIcon)
//    {
//       m_hIcon = hIcon;
//       return *this;
//    }
// 
//    void Attach(HICON hIcon)
//    {
//       if( t_bManaged && m_hIcon != NULL ) ::DestroyIcon(m_hIcon);
//       m_hIcon = hIcon;
//    }  
//    HICON Detach()
//    {
//       HICON hIcon = m_hIcon;
//       m_hIcon = NULL;
//       return hIcon;
//    }
// 
//    operator HICON() const { return m_hIcon; }
// 
//    bool IsNull() const { return m_hIcon == NULL; }
// 
//    // Create methods
// 
//    HICON LoadIcon(_U_STRINGorID icon)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       m_hIcon = ::LoadIcon(_Module.GetResourceInstance(), icon.m_lpstr);
//       return m_hIcon;
//    }
//    HICON LoadIcon(_U_STRINGorID icon, int cxDesired, int cyDesired, UINT fuLoad = 0)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       m_hIcon = (HICON) ::LoadImage(_Module.GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad);
//       return m_hIcon;
//    }
//    HICON LoadOEMIcon(UINT nIDIcon) // for IDI_ types
//    {
//       ATLASSERT(m_hIcon==NULL);
//       m_hIcon = ::LoadIcon(NULL, MAKEINTRESOURCE(nIDIcon));
//       return m_hIcon;
//    }
//    HICON CreateIcon(int nWidth, int nHeight, BYTE cPlanes, BYTE cBitsPixel, CONST BYTE* lpbANDButs, CONST BYTE *lpbXORbits)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(lpbANDbits);
//       ATLASSERT(lpbXORbits);
//       m_hIcon = ::CreateIcon(_Module.GetResourceInstance(), nWidth, nHeight, cPlanes, cBitsPixel, lpbANDbits, lpbXORbits);
//       return m_hIcon;
//    }
//    HICON CreateIconFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(pBits);
//       m_hIcon = ::CreateIconFromResource(pBits, dwResSize, TRUE, dwVersion);
//       return m_hIcon;
//    }
//    HICON CreateIconFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(pbBits);
//       ATLASSERT(cbBits>0);
//       m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, TRUE, dwVersion, cxDesired,  cyDesired, uFlags);
//       return m_hIcon;
//    }
//    HICON CreateIconIndirect(PICONINFO pIconInfo)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(pIconInfo);
//       m_hIcon = ::CreateIconIndirect(pIconInfo);
//       return m_hIcon;
//    }
//    HICON ExtractIcon(LPCTSTR lpszExeFileName, UINT nIconIndex)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(!::IsBadStringPtr(lpszExeFileName,-1));
//       m_hIcon = ::ExtractIcon(_Module.GetModuleInstance(), lpszExeFileName, nIconIndex);
//       return m_hIcon;
//    }
//    HICON ExtractAssociatedIcon(HINSTANCE hInst, LPCTSTR lpIconPath, LPWORD lpiIcon)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(!::IsBadStringPtr(lpIconPath,-1));
//       ATLASSERT(lpiIcon);
//       m_hIcon = ::ExtractAssociatedIcon(hInst, lpIconPath, lpiIcon);
//       return m_hIcon;
//    }
// 
//    // Operations
// 
//    BOOL DestroyIcon()
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       BOOL bRet = ::DestroyIcon(m_hIcon);
//       if( bRet ) m_hIcon = NULL;
//       return bRet;
//    }
//    HICON CopyIcon()
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::CopyIcon(m_hIcon);
//    }
//    HICON DuplicateIcon()
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::DuplicateIcon(NULL, m_hIcon);
//    }
// 
//    BOOL DrawIcon(HDC hDC, int x, int y)
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::DrawIcon(hDC, x, y, m_hIcon);
//    }
//    BOOL DrawIcon(HDC hDC, POINT pt)
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::DrawIcon(hDC, pt.x, pt.y, m_hIcon);
//    }
//    BOOL DrawIconEx(HDC hDC, int x, int y, int cxWidth, int cyWidth, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::DrawIconEx(hDC, x, y, m_hIcon, cxWidth, cyWidth, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
//    }
//    BOOL DrawIconEx(HDC hDC, POINT pt, SIZE size, UINT uStepIfAniCur = 0, HBRUSH hbrFlickerFreeDraw = NULL, UINT uFlags = DI_NORMAL)
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       return ::DrawIconEx(hDC, pt.x, pt.y, m_hIcon, size.cx, size.cy, uStepIfAniCur, hbrFlickerFreeDraw, uFlags);
//    }
// 
//    BOOL GetIconInfo(PICONINFO pIconInfo)
//    {
//       ATLASSERT(m_hIcon!=NULL);
//       ATLASSERT(pIconInfo);
//       return ::GetIconInfo(m_hIcon, pIconInfo);
//    }
// };
// 
// typedef CIconT<true> CIcon;
// typedef CIconT<false> CIconHandle;


/////////////////////////////////////////////////////////////////////////////
// CCursor

// Protect template against silly macro
#ifdef CopyCursor
   #undef CopyCursor
#endif

// template< bool t_bManaged >
// class CCursorT
// {
// public:
//    HCURSOR m_hCursor;
// 
//    // Constructor/destructor/operators
// 
//    CCursorT(HCURSOR hCursor = NULL) : m_hCursor(hCursor)
//    { }
// 
//    ~CCursorT()
//    {
//       if( t_bManaged && m_hCursor != NULL ) ::DestroyCursor(m_hCursor);
//    }
// 
//    CCursorT<t_bManaged>& operator=(HCURSOR hCursor)
//    {
//       m_hCursor = hCursor;
//       return *this;
//    }
// 
//    void Attach(HCURSOR hCursor)
//    {
//       if( t_bManaged && m_hCursor != NULL ) ::DestroyCursor(m_hCursor);
//       m_hCursor = hCursor;
//    }
//    HCURSOR Detach()
//    {
//       HCURSOR hCursor = m_hCursor;
//       m_hCursor = NULL;
//       return hCursor;
//    }
// 
//    operator HCURSOR() const { return m_hCursor; }
// 
//    bool IsNull() const { return m_hCursor == NULL; }
// 
//    // Create methods
// 
//    HCURSOR LoadCursor(_U_STRINGorID cursor)
//    {
//       ATLASSERT(m_hCursor==NULL);
//       m_hCursor = ::LoadCursor(_Module.GetResourceInstance(), cursor.m_lpstr);
//       return m_hCursor;
//    }
//    HCURSOR LoadOEMCursor(UINT nIDCursor) // for IDC_ types
//    {
//       ATLASSERT(m_hCursor==NULL);
//       m_hCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(nIDCursor));
//       return m_hCursor;
//    }
//    HICON LoadCursor(_U_STRINGorID cursor, int cxDesired, int cyDesired, UINT fuLoad = 0)
//    {
//       ATLASSERT(m_hCursor==NULL);
//       m_hCursor = (HCURSOR) ::LoadImage(_Module.GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad);
//       return m_hCursor;
//    }
//    HCURSOR LoadCursorFromFile(LPCTSTR pstrFilename)
//    {
//       ATLASSERT(m_hCursor==NULL);
//       ATLASSERT(!::IsBadStringPtr(pstrFilename,-1));
//       m_hCursor = ::LoadCursorFromFile(pstrFilename);
//       return m_hCursor;
//    }
//    HCURSOR CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, CONST VOID *pvANDPlane, CONST VOID *pvXORPlane)
//    {
//       ATLASSERT(m_hCursor==NULL);
//       m_hCursor = ::CreateCursor(_Module.GetResourceInstance(), xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane);
//       return m_hCursor;
//    }
//    HICON CreateCursorFromResource(PBYTE pBits, DWORD dwResSize, DWORD dwVersion = 0x00030000)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(pBits);
//       m_hIcon = ::CreateIconFromResource(pBits, dwResSize, FALSE, dwVersion);
//       return m_hIcon;
//    }
//    HICON CreateCursorFromResourceEx(PBYTE pbBits, DWORD cbBits, DWORD dwVersion = 0x00030000, int cxDesired = 0, int cyDesired = 0, UINT uFlags = LR_DEFAULTCOLOR)
//    {
//       ATLASSERT(m_hIcon==NULL);
//       ATLASSERT(pbBits);
//       ATLASSERT(cbBits>0);
//       m_hIcon = ::CreateIconFromResourceEx(pbBits, cbBits, FALSE, dwVersion, cxDesired,  cyDesired, uFlags);
//       return m_hIcon;
//    }
//   
//    // Operations
// 
//    BOOL DestroyCursor()
//    {
//       ATLASSERT(m_hCursor!=NULL);
//       BOOL bRet = ::DestroyCursor(m_hCursor);
//       if( bRet ) m_hCursor = NULL;
//       return bRet;
//    }
// 
//    HCURSOR CopyCursor()
//    {
//       ATLASSERT(m_hCursor!=NULL);
//       return (HCURSOR) ::CopyIcon( (HICON) m_hCursor );
//    }
// 
// #if(WINVER >= 0x0500)
//    BOOL GetCursorInfo(LPCURSORINFO pCursorInfo)
//    {
//       ATLASSERT(m_hCursor!=NULL);
//       ATLASSERT(pCursorInfo);
//       return ::GetCursorInfo(pCursorInfo);
//    }
// #endif
// };
// 
// typedef CCursorT<true> CCursor;
// typedef CCursorT<false> CCursorHandle;


/////////////////////////////////////////////////////////////////////////////
// CAccelerator

// template< bool t_bManaged >
// class CAcceleratorT
// {
// public:
//    HACCEL m_hAccel;
// 
//    // Constructor/destructor/operators
// 
//    CAcceleratorT(HACCEL hAccel = NULL) : m_hAccel(hAccel)
//    { }
// 
//    ~CAcceleratorT()
//    {
//       if( t_bManaged && m_hAccel != NULL ) ::DestroyAcceleratorTable(m_hAccel);
//    }
// 
//    CAcceleratorT<t_bManaged>& operator=(HACCEL hAccel)
//    {
//       m_hAccel = hAccel;
//       return *this;
//    }
// 
//    void Attach(HACCEL hAccel)
//    {
//       if( t_bManaged && m_hAccel != NULL ) ::DestroyAcceleratorTable(m_hAccel);
//       m_hAccel = hAccel;
//    }  
//    HCURSOR Detach()
//    {
//       HACCEL hAccel = m_hAccel;
//       m_hAccel = NULL;
//       return hAccel;
//    }
// 
//    operator HACCEL() const { return m_hAccel; }
// 
//    bool IsNull() const { return m_hAccel == NULL; }
// 
//    // Create methods
// 
//    HACCEL LoadAccelerators(_U_STRINGorID accel)
//    {
//       ATLASSERT(m_hAccel==NULL);
//       m_hAccel = ::LoadAccelerators(_Module.GetResourceInstance(), accel.m_lpstr);
//       return m_hAccel;
//    }
//    HACCEL CreateAcceleratorTable(LPACCEL pAccel, int cEntries)
//    {
//       ATLASSERT(m_hAccel==NULL);
//       ATLASSERT(!::IsBadReadPtr(lpAccelDst, sizeof(ACCEL)*cEntries));
//       m_hAccel = ::CreateAcceleratorTable(pAccel, cEntries);
//       return m_hAccel;
//    }
// 
//    // Operations
// 
//    int CopyAcceleratorTable(LPACCEL lpAccelDst, int cEntries)
//    {
//       ATLASSERT(m_hAccel!=NULL);
//       ATLASSERT(!::IsBadWritePtr(lpAccelDst, sizeof(ACCEL)*cEntries));
//       return ::CopyAcceleratorTable(m_hAccel, lpAccelDst, cEntries);
//    }
// 
//    BOOL TranslateAccelerator(HWND hWnd, LPMSG pMsg)
//    {
//       ATLASSERT(m_hAccel!=NULL);
//       ATLASSERT(::IsWindow(hWnd));
//       ATLASSERT(pMsg);
//       return ::TranslateAccelerator(hWnd, m_hAccel, pMsg);
//    }
// };
// 
// typedef CAcceleratorT<true> CAccelerator;
// typedef CAcceleratorT<false> CAcceleratorHandle;


/////////////////////////////////////////////////////////////////////////////
// CLogFont

// class CLogFont : public LOGFONT
// {
// public:
//    CLogFont() 
//    { 
//       ::ZeroMemory( (LOGFONT*) this, sizeof(LOGFONT) );
//    }
//    CLogFont(const LOGFONT& lf) 
//    { 
//       Copy(&lf);
//    }
//    CLogFont(HFONT hFont)
//    {
//       ATLASSERT(::GetObjectType(hFont)==OBJ_FONT);
//       ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*) this);
//    }
//    HFONT CreateFontIndirect() 
//    { 
//       return ::CreateFontIndirect(this); 
//    }
//    void SetBold() 
//    { 
//       lfWeight = FW_BOLD; 
//    }
//    BOOL IsBold() const 
//    { 
//       return lfWeight >= FW_BOLD; 
//    }
//    void MakeBolder(int iScale = 1)
//    {
//       lfWeight += FW_BOLD * iScale;
//    }
//    void MakeLarger(int iScale)
//    {
//       if( lfHeight > 0 ) lfHeight += iScale; else lfHeight -= iScale;
//    }
//    void SetHeight(long PointSize, HDC hDC = NULL) 
//    { 
//       // For MM_TEXT mapping mode...
//       // NOTE: MulDiv() gives correct rounding.
//       lfHeight = -MulDiv(PointSize, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); 
//    }
//    long GetHeight(HDC hDC = NULL) const
//    {
//       // For MM_TEXT mapping mode...
//       // NOTE: MulDiv() gives correct rounding.
//       return ::MulDiv(-lfHeight, 72, ::GetDeviceCaps(hDC, LOGPIXELSY));
//    }
//    long GetDeciPointHeight(HDC hDC = NULL)
//    {
//       POINT ptOrg = { 0, 0 };
//       ::DPtoLP(hDC, &ptOrg, 1);
//       POINT pt = { 0, 0 };
//       pt.y = abs(lfHeight) + ptOrg.y;
//       ::LPtoDP(hDC,&pt,1);
//       return MulDiv(pt.y, 720, ::GetDeviceCaps(hDC,LOGPIXELSY)); // 72 points/inch, 10 decipoints/point
//    }
//    void SetHeightFromDeciPoint(long DeciPtHeight, HDC hDC = NULL)
//    {
//       POINT pt;
//       pt.y = MulDiv(::GetDeviceCaps(hDC, LOGPIXELSY), DeciPtHeight, 720); // 72 points/inch, 10 decipoints/point
//       ::DPtoLP(hDC, &pt, 1);
//       POINT ptOrg = { 0, 0 };
//       ::DPtoLP(hDC, &ptOrg, 1);
//       lfHeight = -abs(pt.y - ptOrg.y);
//    }
//    void SetCaptionFont()
//    {
//       NONCLIENTMETRICS ncm = { 0 };
//       ncm.cbSize = sizeof(ncm);
//       ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
//       Copy(&ncm.lfCaptionFont);
//    }
//    void SetMenuFont()
//    {
//       NONCLIENTMETRICS ncm = { 0 };
//       ncm.cbSize = sizeof(ncm);
//       ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
//       Copy(&ncm.lfMenuFont);
//    }
//    void SetStatusFont()
//    {
//       NONCLIENTMETRICS ncm = { 0 };
//       ncm.cbSize = sizeof(ncm);
//       ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
//       Copy(&ncm.lfStatusFont);
//    }
//    void SetMessageBoxFont()
//    {
//       NONCLIENTMETRICS ncm = { 0 };
//       ncm.cbSize = sizeof(ncm);
//       ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
//       Copy(&ncm.lfMessageFont);
//    }
//    void Copy(const LOGFONT* lf)
//    {
//       ATLASSERT(lf);
//       ::CopyMemory( (LOGFONT*) this, lf, sizeof(LOGFONT) );
//    }
//    CLogFont& operator=(const CLogFont& src)
//    {
//       Copy(&src);
//       return *this;
//    }
//    CLogFont& operator=(const LOGFONT& src)
//    {
//       Copy(&src);
//       return *this;
//    }
//    CLogFont& operator=(HFONT hFont)
//    {
//       ATLASSERT(::GetObjectType(hFont)==OBJ_FONT);
//       ::GetObject(hFont, sizeof(LOGFONT), (LOGFONT*) this);
//       return *this;
//    }
//    bool operator==(const LOGFONT& logfont) const
//    {
//       return( logfont.lfHeight == lfHeight &&
//          logfont.lfWidth == lfWidth &&
//          logfont.lfEscapement == lfEscapement &&
//          logfont.lfOrientation == lfOrientation &&
//          logfont.lfWeight == lfWeight &&
//          logfont.lfItalic == lfItalic &&
//          logfont.lfUnderline == lfUnderline &&
//          logfont.lfStrikeOut == lfStrikeOut &&
//          logfont.lfCharSet == lfCharSet &&
//          logfont.lfOutPrecision == lfOutPrecision &&
//          logfont.lfClipPrecision == lfClipPrecision &&
//          logfont.lfQuality == lfQuality &&
//          logfont.lfPitchAndFamily == lfPitchAndFamily &&
//          ::lstrcmp(logfont.lfFaceName, lfFaceName) == 0 );
//    }
// };
// 

/////////////////////////////////////////////////////////////////////////////
// CMemDC

class CMemDC : public CDC
{
public:
   CDCHandle     m_dc;          // Owner DC
   CBitmap       m_bitmap;      // Offscreen bitmap
   CBitmapHandle m_hOldBitmap;  // Originally selected bitmap
   RECT          m_rc;          // Rectangle of drawing area

   CMemDC(HDC hDC, const LPRECT pRect = NULL)
   {
      ATLASSERT(hDC!=NULL);
      m_dc = hDC;
      if( pRect != NULL ) m_rc = *pRect; else m_dc.GetClipBox(&m_rc);

      CreateCompatibleDC(m_dc);
      ::LPtoDP(m_dc, (LPPOINT) &m_rc, sizeof(RECT)/sizeof(POINT));
      m_bitmap.CreateCompatibleBitmap(m_dc, m_rc.right-m_rc.left, m_rc.bottom-m_rc.top);
      m_hOldBitmap = SelectBitmap(m_bitmap);
      ::DPtoLP(m_dc, (LPPOINT) &m_rc, sizeof(RECT)/sizeof(POINT));
      SetWindowOrg(m_rc.left, m_rc.top);
   }
   ~CMemDC()
   {
      // Copy the offscreen bitmap onto the screen.
      m_dc.BitBlt(m_rc.left, m_rc.top, m_rc.right-m_rc.left, m_rc.bottom-m_rc.top,
                  m_hDC, m_rc.left, m_rc.top, SRCCOPY);
      //Swap back the original bitmap.
      SelectBitmap(m_hOldBitmap);
   }
};


/////////////////////////////////////////////////////////////////////////////
// COffscreenDraw

// To use it, derive from it and chain it in the message map.
template< class T >
class COffscreenDraw
{
public:
   BEGIN_MSG_MAP(COffscreenDraw)
      MESSAGE_HANDLER(WM_PAINT, OnPaint)
      MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
      MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
   END_MSG_MAP()

   LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      T* pT = static_cast<T*>(this);
      if( wParam != NULL )
      {
         CMemDC memdc( (HDC) wParam, NULL );
         pT->DoPaint(memdc.m_hDC);
      }
      else
      {
         RECT rc;
         ::GetClientRect(pT->m_hWnd, &rc);
         CPaintDC dc(pT->m_hWnd);
         CMemDC memdc(dc.m_hDC, &rc);
         pT->DoPaint(memdc.m_hDC);
      }
      return 0;
   }
   LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      return 1; // handled; no need to erase background; do it in DoPaint();
   }
   void DoPaint(CDCHandle dc)
   {
      ATLASSERT(false); // must override this
   }
};

// To use it, derive from it and chain it in the message map.
template< class T >
class COffscreenDrawRect
{
public:
   BEGIN_MSG_MAP(COffscreenDrawRect)
      MESSAGE_HANDLER(WM_PAINT, OnPaint)
      MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
      MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
   END_MSG_MAP()

   LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      T* pT = static_cast<T*>(this);
      if( wParam != NULL )
      {
         CMemDC memdc( (HDC) wParam, NULL );
         pT->DoPaint(memdc.m_hDC, memdc.m_rc);
      }
      else
      {
         CPaintDC dc(pT->m_hWnd);
         CMemDC memdc(dc.m_hDC, &dc.m_ps.rcPaint);
         pT->DoPaint(memdc.m_hDC, dc.m_ps.rcPaint);
      }
      return 0;
   }
   LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
   {
      return 1; // handled; no need to erase background; do it in DoPaint();
   }
   void DoPaint(CDCHandle dc, RECT& rcClip)
   {
      ATLASSERT(false); // must override this
   }
};


/////////////////////////////////////////////////////////////////////////////
// CSaveDC

class CSaveDC
{
public:
   HDC m_hDC;
   int m_iState;

   CSaveDC(HDC hDC) : m_hDC(hDC)
   {
      ATLASSERT(::GetObjectType(m_hDC)==OBJ_DC || ::GetObjectType(m_hDC)==OBJ_MEMDC);
      m_iState = ::SaveDC(hDC);
      ATLASSERT(m_iState!=0);
   }
   ~CSaveDC()
   {
      Restore();
   }
   void Restore()
   {
      if( m_iState == 0 ) return;
      ATLASSERT(::GetObjectType(m_hDC)==OBJ_DC || ::GetObjectType(m_hDC)==OBJ_MEMDC);
      ::RestoreDC(m_hDC, m_iState);
      m_iState = 0;
   }
};


/////////////////////////////////////////////////////////////////////////////
// CHandle

#if (_ATL_VER < 0x0700)

class CHandle
{
public:
   HANDLE m_h;

   CHandle(HANDLE hSrc = INVALID_HANDLE_VALUE) : m_h(hSrc)
   { }

   ~CHandle()
   {
      Close();
   }

   operator HANDLE() const { return m_h; };
  
   LPHANDLE operator&()
   {
      ATLASSERT(!IsValid());
      return &m_h;
   }

   CHandle& operator=(HANDLE h)
   {
      ATLASSERT(!IsValid());
      m_h = h;
      return *this;
   }

   bool IsValid() const { return m_h != INVALID_HANDLE_VALUE; };
   
   void Attach(HANDLE h)
   {
      if( IsValid() ) ::CloseHandle(m_h);
      m_h = h;
   }   
   HANDLE Detach()
   {
      HANDLE h = m_h;
      m_h = INVALID_HANDLE_VALUE;
      return h;
   }
   
   BOOL Close()
   {
      BOOL bRes = FALSE;
      if( m_h != INVALID_HANDLE_VALUE ) {
         bRes = ::CloseHandle(m_h);
         m_h = INVALID_HANDLE_VALUE;
      }
      return bRes;
   }

   BOOL Duplicate(HANDLE hSource, bool bInherit = false)
   {
      ATLASSERT(!IsValid());
      HANDLE hOurProcess = ::GetCurrentProcess();
      BOOL b = ::DuplicateHandle(hOurProcess, 
         hSource,
         hOurProcess, 
         &m_h,
         DUPLICATE_SAME_ACCESS,
         bInherit,
         DUPLICATE_SAME_ACCESS);
      ATLASSERT(b);
      return b;
   }
};

#endif // _ATL_VER


/////////////////////////////////////////////////////////////////////////////
// Mouse Hover helper

#ifndef NOTRACKMOUSEEVENT

#ifndef WM_MOUSEENTER
   #define WM_MOUSEENTER WM_USER + 253
#endif // WM_MOUSEENTER

// To use it, derive from it and chain it in the message map.
// Make sure to set bHandled to FALSE when handling WM_MOUSEMOVE or
// the WM_MOUSELEAVE message!
template< class T >
class CMouseHover
{
public:   
   bool m_fMouseOver;          // Internal mouse-over state
   bool m_fMouseForceUpdate;   // Update window immediately on event

   CMouseHover() : 
      m_fMouseOver(false),
      m_fMouseForceUpdate(true)
   {
   }

   BEGIN_MSG_MAP(CMouseHover)
      MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
      MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
   END_MSG_MAP()

   LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
   {
      T* pT = static_cast<T*>(this);
      if( !m_fMouseOver )   {
         m_fMouseOver = true;
         pT->SendMessage(WM_MOUSEENTER, wParam, lParam);
         pT->Invalidate();
         if( m_fMouseForceUpdate ) pT->UpdateWindow();
         _StartTrackMouseLeave(pT->m_hWnd);
      }
      bHandled = FALSE;
      return 0;
   }
   LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
   {
      T* pT = static_cast<T*>(this);
      if( m_fMouseOver ) {
         m_fMouseOver = false;
         pT->Invalidate();
         if( m_fMouseForceUpdate ) pT->UpdateWindow();
      }
      bHandled = FALSE;
      return 0;
   }
   BOOL _StartTrackMouseLeave(HWND hWnd) const
   {
      ATLASSERT(::IsWindow(hWnd));
      TRACKMOUSEEVENT tme = { 0 };
      tme.cbSize = sizeof(tme);
      tme.dwFlags = TME_LEAVE;
      tme.hwndTrack = hWnd;
      return _TrackMouseEvent(&tme);
   }
   BOOL _CancelTrackMouseLeave(HWND hWnd) const
   {
      TRACKMOUSEEVENT tme = { 0 };
      tme.cbSize = sizeof(tme);
      tme.dwFlags = TME_LEAVE | TME_CANCEL;
      tme.hwndTrack = hWnd;
      return _TrackMouseEvent(&tme);
   }
};

#endif // NOTRACKMOUSEEVENT

//////////////////////////////////////////////////////////////////////////
// added by TuotuoXP


class CLayeredMemDC : public CDC
{

public:

	CLayeredMemDC()
		: m_bUseDIB(true)
	{
//		CWindowDC dc(::GetDesktopWindow());
		CreateCompatibleDC(NULL);
	}

	~CLayeredMemDC()
	{
	}

	void CreateMemDC(int iWidth, int iHeight, bool bUseDIB = true)
	{
		m_bUseDIB = bUseDIB;
		if (m_bUseDIB)
		{
			BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), iWidth, iHeight, 1, 32, BI_RGB };
			m_bmpBuffer.CreateDIBSection(NULL, (BITMAPINFO *) &bmih, 0, (VOID**)&m_pBits, NULL, 0);
		}
		else
		{
			CWindowDC dc(::GetDesktopWindow());
			m_bmpBuffer.CreateCompatibleBitmap(dc, iWidth, iHeight);
		}
 		SelectBitmap(m_bmpBuffer);
	}

	void Release()
	{
		if (m_bmpBuffer)
			m_bmpBuffer.DeleteObject();
	}

	void ChangeSize(int w, int h)
	{
		SIZE sz = { 0, 0 };
		if (m_bmpBuffer)
			m_bmpBuffer.GetSize(sz);
		if (sz.cx != w || sz.cy != h)
		{
			Release();
			CreateMemDC(w, h, m_bUseDIB);
		}
	}

	BYTE *m_pBits; 
	CBitmap m_bmpBuffer;
	bool m_bUseDIB;

};



class CSizableMemDC : public CDC
{

public:

	CBitmap m_bitmap;
	int m_w, m_h;

	CSizableMemDC() : m_w(0), m_h(0) {}

	void Create(HDC hDC, int w, int h)
	{
		if (w != m_w || h != m_h)
		{
			m_w = w;
			m_h = h;
			if (m_hDC)
				DeleteDC();
			if (m_bitmap)
				m_bitmap.DeleteObject();
			if (m_w > 0 && m_h > 0)
			{
				CreateCompatibleDC(hDC);
				BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), m_w, m_h, 1, 32, BI_RGB };
				BYTE *pBits; 
				m_bitmap.CreateDIBSection(NULL, (BITMAPINFO*)&bmih, 0, (VOID**)&pBits, NULL, 0);
				SelectBitmap(m_bitmap);
			}
		}
	}

	~CSizableMemDC()
	{
		if (m_hDC)
			DeleteDC();
		if (m_bitmap)
			m_bitmap.DeleteObject();
	}
};


//////////////////////////////////////////////////////////////////////////

}; // namespace WTL

#endif // __ATLGDIX_H__
